package controladores;

import io.Feed;
import io.SubscriptionDTO;
import java.util.Iterator;
import java.util.List;
import lector.Factory;
import lector.RSSException;
import persistencia.DAOException;
import persistencia.DAOFactory;

/**
 * Clase que representa el controlador de la aplicación, para comunicar la GUI
 * con la Base de Datos y con el Lector RSS.
 *
 * @author Nicolás Garay
 * @author Alejandro Jacquet
 * @author Rita Romani
 */
public class Fachada {

    /**
     * Método que permite insertar una nueva suscripción en la Base de Datos.
     *
     * @param nombre String nombre de la suscripción (unívoco)
     * @param direccion String url de la suscripción
     * @param activo boolean determina si la suscripción se encuentra activa o
     * no
     * @throws DAOException excepción lanzada por la Base de Datos
     */
    public void nuevaSubscription(String nombre, String direccion, boolean activo) throws DAOException {
        DAOFactory.getDAOFactory().getSubscriptionDAO().insertarSubscription(nombre, direccion, activo);
    }

    /**
     * Método que permite eliminar suscripción en la Base de Datos.
     *
     * @param nombre String nombre (unívoco) de la suscripción a eliminar
     * @return boolean determina si la suscripción fue eliminada correctamente o
     * no
     * @throws DAOException excepción lanzada por la Base de Datos
     */
    public boolean eliminarSubscription(String nombre) throws DAOException {
        return DAOFactory.getDAOFactory().getSubscriptionDAO().eliminarSubscription(nombre);
    }

    /**
     * Método que permite modificar una suscripción en la Base de Datos.
     *
     * @param nombreActual String nombre actual de la suscripción
     * @param nombreNuevo String nombre nuevo de la suscripción
     * @param direccion String url de la suscripción
     * @param activo boolean determina si la suscripción se encuentra activa o
     * no
     * @throws DAOException excepción lanzada por la Base de Datos
     */
    public void actualizarSubscription(String nombreActual, String nombreNuevo, String direccion, boolean activo) throws DAOException {
        DAOFactory.getDAOFactory().getSubscriptionDAO().actualizarSubscription(nombreActual, nombreNuevo, direccion, activo);
    }

    /**
     * Método que devuelve una lista con todas las suscripciones almacenadas en
     * la Base de Datos.
     *
     * @return List <SubscriptionDTO>
     * @throws DAOException excepción lanzada por la Base de Datos
     */
    public List<SubscriptionDTO> listarSubscription() throws DAOException {
        return DAOFactory.getDAOFactory().getSubscriptionDAO().listarSubscription();
    }

    /**
     * Método que devuelve la lista de suscripciones almacenada en la Base de
     * Datos, junto con la lectura de los feeds correspondientes a cada
     * suscripción. La lectura de feeds se realiza únicamente para las
     * suscripciones activas pero se devuelven todas las suscripciones en la
     * lista. También permite mantener el atributo abierto para los feeds
     * anterior de cada suscripción pasada como parámetro en
     * listaSubscriptionAnterior.
     *
     * @param listaSubscriptionAnterior List<SubscriptionDTO> lista de
     * suscripciones y feeds anteriores
     * @return List<SubscriptionDTO> lista de suscripciones y feeds actualizados
     * @throws DAOException excepción lanzada por la Base de Datos
     */
    public List<SubscriptionDTO> actualizar(List<SubscriptionDTO> listaSubscriptionAnterior) throws DAOException{
        /* Busca todas las subscripciones almacenadas */
        List<SubscriptionDTO> listaSubscriptionActual = this.listarSubscription();
        /* Iterador que nos permite recorrer la List listaSubscription */
        Iterator<SubscriptionDTO> iterator = listaSubscriptionActual.iterator();
        while (iterator.hasNext()) {
            SubscriptionDTO subscriptionActual = iterator.next();
            /* Obtiene los Feeds de la subscripcion unicamente si la misma esta activa*/
            if (subscriptionActual.getActivo()){
                /* Al leer los feeds con la direccion de la suscripcion se puede producir errores en la lectura,
                 * para poder continuar con las siguientes suscripciones atrapamos la excepcion.
                 */
                try {
                    subscriptionActual.setListaFeeds(Factory.getFactory().getLector().leerFeeds(subscriptionActual.getDireccion()));
                    subscriptionActual.setLecturaExitosa(true);
                } catch (RSSException ex) {
                    /* Este set simboliza que se produjeron errores al leer los feeds de la suscripcion*/
                    subscriptionActual.setLecturaExitosa(false);
                }
            }
            /* Comprobamos que la listaSubscriptionAnterior pasada como parámetro no sea nula,
             * ya que si es nula no es necesaria ninguna comparación con la listaSubscriptionActual
             */
            if ( ! listaSubscriptionAnterior.isEmpty()) {
                /* Este objeto contendrá los atributos que poseia la suscripcion (subscriptionActual) antes de llamar al método,
                 * siempre y cuando la subscriptionActual coincida con alguna de los objetos almacenados en listaSubscriptionAnterior
                 */
                SubscriptionDTO subscriptionAnterior = null;
                SubscriptionDTO subscriptionAuxiliar;
                Iterator<SubscriptionDTO> iteratorSubscriptionAnterior = listaSubscriptionAnterior.iterator();
                /* Iteramos en la listaSubscriptionAnterior para buscar la suscripcion que coincida con subscriptionActual*/
                while (iteratorSubscriptionAnterior.hasNext() && subscriptionAnterior == null){
                    subscriptionAuxiliar = iteratorSubscriptionAnterior.next();
                    if (subscriptionAuxiliar.equals(subscriptionActual)){
                        subscriptionAnterior = subscriptionAuxiliar;
                    }
                }
                /*   Si la subscriptionAnterior no es null quiere decir que encontramos la suscripcion que coincide con subscriptionActual,
                 * entonces podemos comparar los objetos Feed de cada una de las suscripciones.
                 *   Tambien comprobamos que tanto subscriptionAnterior como subscriptionActual hayan tenido lecturas exitosas en sus Feeds,
                 * ya que si en alguna esto no hubiese ocurrido la comparación de objetos Feed no tiene sentido.
                 */
                if (subscriptionAnterior != null && subscriptionAnterior.isLecturaExitosa() && subscriptionActual.isLecturaExitosa()){
                    List<Feed> listaFeedsActual = subscriptionActual.getListaFeeds();
                    List<Feed> listaFeedsAnterior = subscriptionAnterior.getListaFeeds();
                    Iterator<Feed> iteratorFeedAnterior = listaFeedsAnterior.iterator();
                    Feed feedAnterior;
                    Feed feedAuxiliar;
                    Feed feedActual;
                    /* Iteramos cada uno de los objetos Feed que se encuentran en subscriptionAnterior*/
                    while(iteratorFeedAnterior.hasNext()){
                        feedAnterior = iteratorFeedAnterior.next();
                        feedAuxiliar = null;
                        Iterator<Feed> iteratorFeedActual = listaFeedsActual.iterator();
                        /* Iteramos cada uno de los objetos Feed que se encuentran en subscriptionActual,
                         * para buscar si se encuentra el feedAnterior
                         */
                        while (iteratorFeedActual.hasNext() && feedAuxiliar == null){
                            feedActual = iteratorFeedActual.next();
                            /*  Si el feedAnterior se encuentra entonces le seteamos a feedActual el atributo "abierto"
                             * de feedAnterior
                             */
                            if(feedActual.equals(feedAnterior)){
                                feedActual.setAbierto(feedAnterior.isAbierto());
                                feedAuxiliar= feedAnterior;
                            }
                        }
                    }
                }
            }
        }
        return listaSubscriptionActual;
    }
}
